Spring JDBC-এর সাথে টেস্টিং একটি গুরুত্বপূর্ণ বিষয়, কারণ এটি ডেটাবেসের সাথে সরাসরি কাজ করে এবং ডেটা অ্যাক্সেস লেয়ারের সঠিকতা নিশ্চিত করতে সাহায্য করে। Spring Framework ডেটাবেস টেস্টিংয়ের জন্য বিভিন্ন টুল এবং পদ্ধতি সরবরাহ করে, যা ইউনিট টেস্ট, ইন্টিগ্রেশন টেস্ট, এবং ডেটাবেস ইনিশিয়ালাইজেশনের কাজ সহজ করে।
Spring JDBC টেস্টিং কেন গুরুত্বপূর্ণ?
- ডেটা এক্সেস লেয়ারের সঠিকতা নিশ্চিত করা:
- ডেটাবেসে CRUD অপারেশন এবং কুয়েরি লজিক সঠিকভাবে কাজ করছে কিনা তা যাচাই করতে।
- ডেটাবেসের অবস্থান নিশ্চিত করা:
- ডেটাবেস টেবিল, ডেটা ইন্টিগ্রিটি এবং রিলেশনাল ম্যাপিং যাচাই করা।
- বাগ সনাক্তকরণ এবং প্রতিরোধ:
- প্রোডাকশনের আগে ত্রুটি খুঁজে পাওয়া।
- অটোমেটেড টেস্টিং:
- ডেটাবেস সংক্রান্ত লজিক অটোমেটেডভাবে যাচাই করা যায়।
Spring JDBC টেস্টিংয়ের জন্য প্রয়োজনীয় সরঞ্জাম
- JUnit বা TestNG:
- টেস্টিং ফ্রেমওয়ার্ক হিসাবে ব্যবহৃত হয়।
- Spring Test Framework:
- Spring এর টেস্টিং ইউটিলিটি ক্লাস এবং এনোটেশন ব্যবহার করা হয়।
- Embedded Databases (H2, HSQLDB):
- হালকা ওজনের এমবেডেড ডেটাবেস ব্যবহার করে টেস্টিং করা হয়।
- Spring JDBC Test Utilities:
JdbcTestUtilsক্লাস এবং অন্যান্য ইউটিলিটি।
Spring JDBC টেস্টিং পদ্ধতি
১. TestConfiguration: Test Context তৈরি করা
Spring টেস্ট কনফিগারেশন সেটআপ করার জন্য @Configuration বা @TestConfiguration ব্যবহার করা হয়।
@Configuration
public class TestConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql") // স্ক্রিপ্ট থেকে টেবিল তৈরি
.addScript("data.sql") // প্রাথমিক ডেটা লোড
.build();
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
২. JUnit এবং Spring Integration ব্যবহার করা
@SpringJUnitConfig(TestConfig.class) // TestConfig কনফিগারেশন ব্যবহার
public class UserRepositoryTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testGetUserById() {
String sql = "SELECT name FROM users WHERE id = ?";
String name = jdbcTemplate.queryForObject(sql, new Object[]{1}, String.class);
assertEquals("John Doe", name); // টেস্ট যাচাই
}
}
৩. Embedded Database ব্যবহার করে টেস্ট করা
Spring টেস্টিংয়ের সময় H2 বা HSQLDB এর মতো এমবেডেড ডেটাবেস ব্যবহার করলে প্রকৃত ডেটাবেসের প্রয়োজন হয় না।
public class UserRepositoryTest {
@Test
public void testInsertUser() {
EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.addScript("data.sql")
.build();
JdbcTemplate jdbcTemplate = new JdbcTemplate(db);
String insertSql = "INSERT INTO users (name, email) VALUES (?, ?)";
jdbcTemplate.update(insertSql, "Jane Doe", "jane.doe@example.com");
String querySql = "SELECT COUNT(*) FROM users";
int count = jdbcTemplate.queryForObject(querySql, Integer.class);
assertEquals(3, count); // ডেটা যাচাই
}
}
৪. Transactional টেস্টিং
@Transactional এনোটেশন ব্যবহার করে, প্রতিটি টেস্টের পরে ডেটা রোলব্যাক নিশ্চিত করা যায়।
@SpringJUnitConfig(TestConfig.class)
@Transactional
public class TransactionalTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testInsertUser() {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
jdbcTemplate.update(sql, "Mark Smith", "mark.smith@example.com");
String countSql = "SELECT COUNT(*) FROM users";
int count = jdbcTemplate.queryForObject(countSql, Integer.class);
assertEquals(3, count); // রোলব্যাক হওয়ার আগে যাচাই
}
}
৫. JdbcTestUtils ব্যবহার করে টেবিল যাচাই
Spring এর JdbcTestUtils ক্লাস ব্যবহার করে টেবিলের রেকর্ড গণনা সহজ।
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.jdbc.JdbcTestUtils;
@SpringJUnitConfig(TestConfig.class)
public class JdbcTestUtilsExample {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testRowCount() {
int rowCount = JdbcTestUtils.countRowsInTable(jdbcTemplate, "users");
assertEquals(2, rowCount); // টেবিলের রেকর্ড সংখ্যা যাচাই
}
}
Spring JDBC টেস্টিং-এর ভালো অভ্যাস
- Embedded Database ব্যবহার:
- টেস্টিংয়ের জন্য প্রোডাকশন ডেটাবেসের উপর নির্ভর না করা।
- Transactional টেস্টিং:
- প্রতিটি টেস্টের পরে ডেটা রোলব্যাক নিশ্চিত করা।
- ডেটা ইনিশিয়ালাইজেশনের জন্য SQL স্ক্রিপ্ট:
- টেস্ট শুরু করার আগে ডেটা লোড করার জন্য
schema.sqlএবংdata.sqlব্যবহার করা।
- টেস্ট শুরু করার আগে ডেটা লোড করার জন্য
- স্প্রিং কনটেক্সট পুনঃব্যবহার:
@DirtiesContextএড়িয়ে স্প্রিং কনটেক্সট পুনঃব্যবহার করা।
- JUnit Assertions ব্যবহার:
assertEquals(),assertTrue()ইত্যাদি ব্যবহার করে টেস্ট ফলাফল যাচাই করা।
উপসংহার
Spring JDBC-এর সাথে টেস্টিং গুরুত্বপূর্ণ কারণ এটি ডেটাবেস অপারেশন নিশ্চিত করতে সাহায্য করে। Spring Framework এর টুল এবং কনভেনশনগুলো টেস্টিং সহজ এবং কার্যকর করে। Embedded Database, @Transactional এবং Spring Test Framework এর সমন্বয়ে টেস্টিং আরও সুনির্দিষ্ট এবং নির্ভরযোগ্য হয়।
Spring JDBC প্রজেক্টে ডাটাবেস অ্যাক্সেস কোডের নির্ভুলতা ও কার্যকারিতা নিশ্চিত করার জন্য Unit Testing এবং Integration Testing অত্যন্ত গুরুত্বপূর্ণ।
Testing কেন প্রয়োজন?
- ডাটাবেসের সাথে ইন্টিগ্রেশন নিশ্চিত করা:
Spring JDBC-এর মাধ্যমে ডাটাবেসের সাথে সংযোগ এবং ডাটার যথাযথ আদান-প্রদান কাজ করছে কিনা তা নিশ্চিত করতে। - বাগ সনাক্তকরণ ও সমাধান:
ডাটাবেসের কনফিগারেশন, SQL কুয়েরি, বা ব্যবসায়িক লজিক সম্পর্কিত সমস্যা সময়মতো সনাক্ত করা। - ডাটাবেস নির্ভর কোডের স্থায়িত্ব:
ডাটাবেস কোড ভবিষ্যতের পরিবর্তনের সাথে সামঞ্জস্যপূর্ণ কিনা তা পরীক্ষা করতে। - স্বয়ংক্রিয়তা:
ম্যানুয়াল ডাটাবেস পরীক্ষার সময় এবং প্রচেষ্টা হ্রাস করে স্বয়ংক্রিয় টেস্টিং পদ্ধতির উপর নির্ভর করা। - রিগ্রেশন প্রতিরোধ:
নতুন কোড যোগ করার সময় পুরানো কোড কাজ করছে কিনা তা নিশ্চিত করা।
Unit Testing
Unit Testing কী?
Unit Testing হলো কোডের একটি ছোট অংশ (যেমন একটি মেথড বা ক্লাস) আলাদাভাবে পরীক্ষা করা। Spring JDBC-তে Unit Testing করার সময় আসল ডাটাবেস ব্যবহার করা হয় না; পরিবর্তে, মক করা অবজেক্ট ব্যবহার করা হয়।
Spring JDBC-তে Unit Testing-এর সুবিধা:
- দ্রুত এক্সিকিউশন (ডাটাবেসের উপর নির্ভর করে না)।
- শুধুমাত্র নির্দিষ্ট লজিক পরীক্ষা করা হয়।
- নির্ভরশীল ডাটাবেস ছাড়াই কার্যকরী।
Spring JDBC-তে Unit Testing উদাহরণ:
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.jdbc.core.JdbcTemplate;
class EmployeeServiceTest {
@Mock
private JdbcTemplate jdbcTemplate;
@InjectMocks
private EmployeeService employeeService;
@Test
void testGetEmployeeCount() {
// Mocking JdbcTemplate response
when(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM employees", Integer.class)).thenReturn(5);
// Test method
int count = employeeService.getEmployeeCount();
// Verify and assert
assertEquals(5, count);
verify(jdbcTemplate, times(1)).queryForObject("SELECT COUNT(*) FROM employees", Integer.class);
}
}
Integration Testing
Integration Testing কী?
Integration Testing সিস্টেমের বিভিন্ন অংশ (যেমন: Spring Context, DAO, এবং ডাটাবেস) একত্রে কাজ করছে কিনা তা পরীক্ষা করে। এটি সাধারণত একটি বাস্তব ডাটাবেস বা ইন-মেমরি ডাটাবেস (যেমন H2) ব্যবহার করে।
Spring JDBC-তে Integration Testing-এর সুবিধা:
- আসল ডাটাবেসের সাথে কাজ করে।
- SQL কুয়েরি এবং ডাটাবেস স্কিমা সঠিক কিনা তা যাচাই করে।
- Spring Configuration সঠিকভাবে সেটআপ করা হয়েছে কিনা তা নিশ্চিত করে।
Integration Testing উদাহরণ:
H2 ডাটাবেস ব্যবহার করে টেস্ট:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import static org.junit.jupiter.api.Assertions.*;
@JdbcTest
@Import(EmployeeService.class) // Importing the service
class EmployeeServiceIntegrationTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private EmployeeService employeeService;
@Test
void testAddEmployee() {
// Pre-check database state
int initialCount = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM employees", Integer.class);
// Add an employee
employeeService.addEmployee("John Doe", "HR", 50000);
// Verify database changes
int updatedCount = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM employees", Integer.class);
assertEquals(initialCount + 1, updatedCount);
// Check inserted data
String name = jdbcTemplate.queryForObject("SELECT name FROM employees WHERE name = ?",
new Object[]{"John Doe"}, String.class);
assertEquals("John Doe", name);
}
}
Unit Testing বনাম Integration Testing
| প্যারামিটার | Unit Testing | Integration Testing |
|---|---|---|
| অংশ | শুধুমাত্র একটি মেথড বা ক্লাস পরীক্ষা করা হয়। | পুরো সিস্টেম বা একাধিক অংশ একত্রে পরীক্ষা করা। |
| ডাটাবেস | মক ডাটাবেস ব্যবহার করা হয়। | আসল বা ইন-মেমরি ডাটাবেস ব্যবহার করা হয়। |
| গতি | দ্রুত কারণ এটি ডাটাবেসে নির্ভর করে না। | তুলনামূলকভাবে ধীর কারণ এটি ডাটাবেসে কাজ করে। |
| জটিলতা | সহজ এবং নির্দিষ্ট লজিকের জন্য আদর্শ। | জটিল সিস্টেম ইন্টিগ্রেশন পরীক্ষা করতে ব্যবহৃত। |
| ব্যবহার ক্ষেত্র | ব্যবসায়িক লজিকের জন্য। | ডাটাবেস এবং অ্যাপ্লিকেশন ইন্টিগ্রেশন নিশ্চিত করতে। |
টেস্টিং স্ট্র্যাটেজি
- Unit Testing শুরুতে করুন:
- মেথড এবং ক্লাসগুলো সঠিকভাবে কাজ করছে কিনা তা নিশ্চিত করতে।
- Integration Testing চালান:
- ডাটাবেস এবং Spring Context-এর সাথে সমস্ত কোড সঠিকভাবে কাজ করছে কিনা তা যাচাই করতে।
- In-Memory Database ব্যবহার করুন:
- Integration Testing-এর জন্য H2 বা HSQLDB ব্যবহার করুন যাতে ডাটাবেস সেটআপ সহজ হয়।
- Continuous Integration:
- প্রতিটি কোড পরিবর্তনের পর টেস্ট অটোমেটিকভাবে চালানোর জন্য CI টুল (যেমন Jenkins বা GitHub Actions) ব্যবহার করুন।
উপসংহার
Spring JDBC প্রজেক্টে Unit Testing এবং Integration Testing উভয়ই গুরুত্বপূর্ণ:
- Unit Testing ব্যবসায়িক লজিক এবং কোডের নির্ভুলতা নিশ্চিত করে।
- Integration Testing ডাটাবেস এবং Spring এর সঠিক ইন্টিগ্রেশন যাচাই করে।
উভয়ের সমন্বয় একটি শক্তিশালী এবং নির্ভরযোগ্য অ্যাপ্লিকেশন গড়ে তোলার ভিত্তি।
H2 ডেটাবেস একটি ইন-মেমরি ডেটাবেস, যা সহজ এবং দ্রুত টেস্টিংয়ের জন্য আদর্শ। Spring JDBC এবং H2 ডেটাবেস একসাথে ব্যবহার করে আপনি টেস্টিং প্রক্রিয়া আরও কার্যকর করতে পারেন। এটি সহজেই ইন-মেমরি ডেটাবেস তৈরি করে, যেখানে ডেটা অস্থায়ীভাবে সংরক্ষিত হয় এবং অ্যাপ্লিকেশন বন্ধ হওয়ার সাথে সাথে ডেটা মুছে যায়।
H2 Database এবং Spring JDBC এর মাধ্যমে টেস্টিং করার ধাপসমূহ
ধাপ ১: Maven ডিপেনডেন্সি যোগ করা
Spring এবং H2 ডেটাবেস ব্যবহার করার জন্য নিচের ডিপেনডেন্সি যুক্ত করুন:
<dependencies>
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.21</version>
</dependency>
<!-- H2 Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
<scope>test</scope>
</dependency>
<!-- JUnit (Testing Framework) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
</dependencies>
ধাপ ২: H2 ডেটাবেসের জন্য Spring Configuration তৈরি করা
Spring টেস্ট কনফিগারেশন তৈরি করুন, যেখানে H2 ডেটাবেস এবং JdbcTemplate কনফিগার করবেন।
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@Configuration
public class TestConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
ধাপ ৩: SQL Schema এবং ডেটা সেটআপ
schema.sql এবং data.sql ফাইল তৈরি করুন।
Spring Boot টেস্ট চলাকালীন এই ফাইলগুলো স্বয়ংক্রিয়ভাবে লোড করবে।
schema.sql:
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
department VARCHAR(50)
);
data.sql:
INSERT INTO employees (id, name, department) VALUES (1, 'John Doe', 'IT');
INSERT INTO employees (id, name, department) VALUES (2, 'Jane Smith', 'HR');
ধাপ ৪: টেস্টিং ক্লাস তৈরি করা
Spring টেস্টিং পরিবেশে H2 ডেটাবেস ব্যবহার করে টেস্টিং করার জন্য JUnit ব্যবহার করুন।
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest(classes = TestConfig.class)
public class EmployeeServiceTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testFetchEmployees() {
// Fetch all employees
String query = "SELECT * FROM employees";
List<Map<String, Object>> employees = jdbcTemplate.queryForList(query);
// Verify the data
assertEquals(2, employees.size());
assertEquals("John Doe", employees.get(0).get("name"));
assertEquals("Jane Smith", employees.get(1).get("name"));
}
@Test
public void testAddEmployee() {
// Insert a new employee
String insertQuery = "INSERT INTO employees (id, name, department) VALUES (?, ?, ?)";
int rowsAffected = jdbcTemplate.update(insertQuery, 3, "Alice Brown", "Finance");
// Verify the data
assertEquals(1, rowsAffected);
// Fetch and verify
String fetchQuery = "SELECT * FROM employees WHERE id = ?";
Map<String, Object> employee = jdbcTemplate.queryForMap(fetchQuery, 3);
assertEquals("Alice Brown", employee.get("name"));
assertEquals("Finance", employee.get("department"));
}
}
Spring Boot-এর জন্য H2 ব্যবহার সহজীকরণ
Spring Boot টেস্টিংয়ের সময় schema.sql এবং data.sql ফাইলগুলো স্বয়ংক্রিয়ভাবে লোড করা যায়। এটির জন্য কোনো অতিরিক্ত কনফিগারেশন প্রয়োজন নেই।
Application.properties:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.schema=classpath:schema.sql
spring.datasource.data=classpath:data.sql
Spring Boot চালু হওয়ার সময় এটি H2 ডেটাবেস সেটআপ করবে এবং SQL স্ক্রিপ্টগুলো লোড করবে।
H2 Database Console ব্যবহার
টেস্ট চলাকালীন H2 ডেটাবেসের ডেটা দেখতে কনসোল ব্যবহার করতে পারেন।
Application.properties:
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
H2 কনসোল অ্যাক্সেস করতে ব্রাউজারে যান:
http://localhost:8080/h2-console
ড্রাইভার: org.h2.Driver
জড়ু URL: jdbc:h2:mem:testdb
H2 Database ব্যবহার করার সুবিধা
- ইন-মেমরি ডেটাবেস: দ্রুত এবং অস্থায়ী ডেটা ব্যবস্থাপনা।
- সহজ সেটআপ: Spring Boot বা Spring Framework এর সাথে সহজে ইন্টিগ্রেশন।
- ডেভেলপমেন্ট এবং টেস্টিং ফ্রেন্ডলি: ডেটাবেস ম্যানেজমেন্ট ছাড়াই টেস্টিং করা যায়।
- কনসোল সাপোর্ট: সহজে ডেটাবেস স্ট্রাকচার এবং ডেটা পরীক্ষা করা যায়।
উপসংহার
H2 ডেটাবেস Spring JDBC টেস্টিংয়ের জন্য একটি সহজ, দ্রুত এবং কার্যকর সমাধান। এটি ইন-মেমরি হওয়ায় টেস্টিংয়ের সময় কোনো স্থায়ী ডেটাবেসের প্রয়োজন হয় না। Spring Boot-এর সাহায্যে H2 ইন্টিগ্রেশন আরও সহজ এবং সময়সাশ্রয়ী হয়।
Spring Test Framework হলো স্প্রিং অ্যাপ্লিকেশনগুলোর টেস্টিং এর জন্য একটি শক্তিশালী এবং ফিচার-সমৃদ্ধ ফ্রেমওয়ার্ক। এটি বিভিন্ন কনটেক্সট এবং কম্পোনেন্টের কার্যকারিতা নিশ্চিত করতে সাহায্য করে। @JdbcTest অ্যানোটেশনটি বিশেষভাবে স্প্রিং জেডিবিসি-ভিত্তিক টেস্টিংয়ের জন্য ব্যবহৃত হয়।
@JdbcTest কী?
- @JdbcTest হলো একটি স্প্রিং বুট টেস্টিং অ্যানোটেশন যা শুধুমাত্র স্প্রিং জেডিবিসি কম্পোনেন্ট (যেমন,
JdbcTemplate) এবং রিলেটেড বিনগুলো টেস্ট করার জন্য ব্যবহৃত হয়। - এটি একটি লাইটওয়েট টেস্টিং এনভায়রনমেন্ট তৈরি করে যেখানে শুধুমাত্র ডাটাবেস অপারেশন এবং ডাটা অ্যাক্সেস টেস্ট করা যায়।
- সাধারণত এটি H2 Database বা Embedded Database এর সাথে ব্যবহার করা হয়।
@JdbcTest এর বৈশিষ্ট্য
- Minimal Configuration:
- শুধুমাত্র ডাটাবেস-সম্পর্কিত কনটেক্সট লোড করে।
- অন্যান্য অপ্রয়োজনীয় বিন বা কনফিগারেশন লোড করে না।
- Auto-configured Database:
- ডাটাবেস টেস্টের জন্য ইন-মেমরি ডাটাবেস (যেমন, H2) স্বয়ংক্রিয়ভাবে কনফিগার করে।
- Transactional Support:
- প্রতিটি টেস্ট স্বয়ংক্রিয়ভাবে একটি ট্রানজেকশন ব্লকে চলে এবং টেস্ট শেষে rollback করা হয়।
- Integration with Flyway/Liquibase:
- ডাটাবেস স্কিমা মাইগ্রেশন টুলের সাপোর্ট দেয়।
কনফিগারেশন এবং উদাহরণ
১. Dependency যোগ করা
Maven ব্যবহার করলে নিচের ডিপেন্ডেন্সি যোগ করতে হবে:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
২. Entity এবং Repository তৈরি করা
Student Entity:
public class Student {
private int id;
private String name;
private int age;
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Student Repository:
@Repository
public class StudentRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Student> findAll() {
String sql = "SELECT id, name, age FROM students";
return jdbcTemplate.query(sql, (rs, rowNum) -> {
Student student = new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"));
student.setAge(rs.getInt("age"));
return student;
});
}
}
৩. Test Case তৈরি করা
Test Class:
@JdbcTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY) // Use in-memory database
public class StudentRepositoryTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private StudentRepository studentRepository;
@Test
public void testFindAll() {
// প্রাথমিক ডাটা ইনসার্ট করা
jdbcTemplate.execute("INSERT INTO students (id, name, age) VALUES (1, 'John Doe', 20)");
jdbcTemplate.execute("INSERT INTO students (id, name, age) VALUES (2, 'Jane Doe', 22)");
// মেথড টেস্ট করা
List<Student> students = studentRepository.findAll();
// যাচাই করা
assertEquals(2, students.size());
assertEquals("John Doe", students.get(0).getName());
assertEquals(20, students.get(0).getAge());
}
}
বিস্তারিত ব্যাখ্যা
1. @JdbcTest অ্যানোটেশন:
- এটি Spring Context তৈরি করে যা শুধুমাত্র JDBC সম্পর্কিত বীনগুলো লোড করে।
2. @AutoConfigureTestDatabase:
- ইন-মেমরি ডাটাবেস (যেমন, H2) ব্যবহার করতে বলে।
replace = AutoConfigureTestDatabase.Replace.ANYস্বয়ংক্রিয়ভাবে ইন-মেমরি ডাটাবেস কনফিগার করে।
3. Data Preparation:
jdbcTemplate.execute()ব্যবহার করে টেস্টের জন্য প্রাথমিক ডাটা যোগ করা হয়।
4. Assertion:
- JUnit বা TestNG ব্যবহার করে মেথডের আউটপুট যাচাই করা হয়।
Flyway/Liquibase Integration
যদি ডাটাবেস স্কিমা মাইগ্রেশনের জন্য Flyway বা Liquibase ব্যবহার করা হয়, তবে এটি @JdbcTest-এর সাথে স্বয়ংক্রিয়ভাবে কাজ করে।
Flyway Example:
application.properties:
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
@JdbcTest এর সুবিধা
- লাইটওয়েট টেস্টিং:
- শুধুমাত্র প্রয়োজনীয় বীন লোড করে, ফলে টেস্ট দ্রুত চলে।
- ইন-মেমরি ডাটাবেস ব্যবহার:
- ডাটাবেস টেস্টের জন্য সহজ এবং দ্রুত।
- Rollback Support:
- প্রতিটি টেস্ট শেষে ডেটাবেস স্বয়ংক্রিয়ভাবে পূর্বাবস্থায় ফেরত যায়।
- স্বয়ংক্রিয় কনফিগারেশন:
- কম কনফিগারেশন প্রয়োজন।
উপসংহার
Spring Test Framework এবং @JdbcTest অ্যানোটেশন ব্যবহার করে Spring JDBC ভিত্তিক ডাটাবেস টেস্ট করা খুবই সহজ এবং কার্যকর। এটি লাইটওয়েট টেস্টিং পরিবেশ প্রদান করে এবং ডেভেলপারদের ডাটাবেস-সম্পর্কিত মেথডগুলোর সঠিকতা যাচাই করতে সহায়তা করে। @JdbcTest এবং ইন-মেমরি ডাটাবেস (যেমন, H2) ব্যবহার করে টেস্টিং আরও দ্রুত এবং সুনির্দিষ্ট হয়।
স্প্রিং জেডিবিসি (Spring JDBC) অ্যাপ্লিকেশনটি পরীক্ষা (Testing) করা গুরুত্বপূর্ণ, কারণ এটি নিশ্চিত করে যে আপনার ডেটাবেস ইন্টারঅ্যাকশন সঠিকভাবে কাজ করছে। স্প্রিং জেডিবিসি টেস্টিংয়ে সাধারণত JUnit এবং Mockito ব্যবহৃত হয়, যেখানে JdbcTemplate এর কার্যকারিতা পরীক্ষার জন্য ফেইক বা মক (mock) ডেটাবেস ব্যবহার করা হয়।
স্প্রিং জেডিবিসি টেস্টিং করার জন্য আমরা সাধারণত দুটি পদ্ধতি ব্যবহার করি:
- Integration Testing (প্রকৃত ডেটাবেসের সাথে)
- Unit Testing (Mockito বা H2 ডেটাবেস ব্যবহার করে)
1. Spring JDBC Integration Testing (প্রকৃত ডেটাবেসের সাথে)
Integration Testing এর মধ্যে আমরা প্রকৃত ডেটাবেস (যেমন H2 ইন-মেমরি ডেটাবেস) ব্যবহার করি, যাতে আমরা নিশ্চিত হতে পারি যে আমাদের কোড ডেটাবেসের সাথে সঠিকভাবে কাজ করছে।
1.1. H2 ইন-মেমরি ডেটাবেস ব্যবহার
H2 একটি ইন-মেমরি ডেটাবেস যা স্প্রিং জেডিবিসি পরীক্ষার জন্য বেশ উপযুক্ত। এটি কোনো নির্দিষ্ট কনফিগারেশন ছাড়াই ডেটাবেস তৈরি করতে সহায়ক।
pom.xml এ H2 ডিপেনডেন্সি যুক্ত করুন:
<dependencies>
<!-- Spring JDBC Dependency -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.20</version>
</dependency>
<!-- H2 Database for testing -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>test</scope>
</dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<!-- Spring Test Dependency -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.20</version>
<scope>test</scope>
</dependency>
</dependencies>
1.2. Spring JDBC Testing Example
ধরা যাক আমাদের একটি EmployeeDao ক্লাস রয়েছে যা JdbcTemplate ব্যবহার করে ডেটাবেস থেকে ডেটা রিট্রিভ বা ইনসার্ট করে। এখন এই ক্লাসটির টেস্ট করতে হবে।
EmployeeDao.java:
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class EmployeeDao {
private JdbcTemplate jdbcTemplate;
public EmployeeDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void addEmployee(int id, String name, double salary) {
String sql = "INSERT INTO Employee (id, name, salary) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, id, name, salary);
}
public Employee getEmployee(int id) {
String sql = "SELECT * FROM Employee WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper<>(Employee.class));
}
}
Integration Test with H2:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
public class EmployeeDaoTest {
@Autowired
private EmployeeDao employeeDao;
@Autowired
private JdbcTemplate jdbcTemplate;
@BeforeEach
public void setup() {
// Set up in-memory H2 database for testing
jdbcTemplate.execute("CREATE TABLE Employee (id INT, name VARCHAR(255), salary DOUBLE)");
}
@Test
public void testAddEmployee() {
// Test the insert functionality
employeeDao.addEmployee(1, "John Doe", 50000);
Employee employee = employeeDao.getEmployee(1);
assertNotNull(employee);
assertEquals("John Doe", employee.getName());
assertEquals(50000, employee.getSalary());
}
@Test
public void testGetEmployee() {
// Add employee for testing
jdbcTemplate.update("INSERT INTO Employee (id, name, salary) VALUES (2, 'Jane Smith', 60000)");
Employee employee = employeeDao.getEmployee(2);
assertNotNull(employee);
assertEquals("Jane Smith", employee.getName());
assertEquals(60000, employee.getSalary());
}
}
ব্যাখ্যা:
@SpringBootTest: এটি স্প্রিং অ্যাপ্লিকেশন কনটেক্সট লোড করতে ব্যবহৃত হয়, যাতেEmployeeDaoক্লাস এবংJdbcTemplateক্লাস টেস্ট করা যায়।@Autowired: স্প্রিং দ্বারাEmployeeDaoএবংJdbcTemplateইনজেক্ট করা হয়।- H2 ডেটাবেস: টেস্ট শুরু করার আগে
CREATE TABLESQL স্টেটমেন্টের মাধ্যমে টেস্ট ডেটাবেস তৈরি করা হয়। - JUnit assertions:
assertNotNullএবংassertEqualsমেথড ব্যবহার করা হয়েছে নিশ্চিত করতে যে ইনসার্ট এবং রিটার্ন অপারেশন সঠিকভাবে কাজ করছে।
2. Spring JDBC Unit Testing with Mockito
Mockito ব্যবহার করে Unit Testing করতে গেলে, আমরা ডেটাবেস ইন্টারঅ্যাকশন মক করতে পারি, যাতে প্রকৃত ডেটাবেস কনফিগারেশন ছাড়া শুধুমাত্র লজিক টেস্ট করা যায়। এখানে আমরা Mockito এবং JdbcTemplate মক করতে দেখাবো।
2.1. Mockito Setup:
pom.xml এ Mockito ডিপেনডেন্সি যুক্ত করুন:
<dependencies>
<!-- Mockito for Unit Testing -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.5.0</version>
<scope>test</scope>
</dependency>
</dependencies>
2.2. Unit Test with Mockito:
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
@ExtendWith(MockitoExtension.class)
public class EmployeeDaoUnitTest {
@Mock
private JdbcTemplate jdbcTemplate;
@InjectMocks
private EmployeeDao employeeDao;
@Test
public void testGetEmployee() {
// Arrange
Employee mockEmployee = new Employee(1, "John Doe", 50000);
when(jdbcTemplate.queryForObject(anyString(), any(Object[].class), any(BeanPropertyRowMapper.class)))
.thenReturn(mockEmployee);
// Act
Employee employee = employeeDao.getEmployee(1);
// Assert
assertNotNull(employee);
assertEquals("John Doe", employee.getName());
assertEquals(50000, employee.getSalary());
}
@Test
public void testAddEmployee() {
// Arrange
doNothing().when(jdbcTemplate).update(anyString(), any(), any(), any());
// Act
employeeDao.addEmployee(2, "Jane Smith", 60000);
// Assert
verify(jdbcTemplate, times(1)).update(anyString(), any(), any(), any());
}
}
ব্যাখ্যা:
- Mockito Mocks:
@Mockদিয়েJdbcTemplateকে মক করা হয়েছে যাতে প্রকৃত ডেটাবেস অ্যাক্সেস না হয়। when()এবংthenReturn(): মক স্টেটমেন্টের জন্য ব্যবহার করা হয়েছে, যাতেjdbcTemplate.queryForObject()মেথড একটি নির্দিষ্ট মান রিটার্ন করে।verify(): পরীক্ষা করা হয়েছে যেupdate()মেথড একবার কল করা হয়েছে কিনা।
উপসংহার:
- Integration Testing তে প্রকৃত ডেটাবেস ব্যবহার করা হয় যাতে ডেটাবেস ইন্টারঅ্যাকশন সঠিকভাবে কাজ করছে কিনা তা পরীক্ষা করা যায়।
- Unit Testing তে Mockito ব্যবহার করে শুধুমাত্র ডেটাবেস ইন্টারঅ্যাকশন নয়,
JdbcTemplateএর মতো ক্লাসও মক করা যায়। - দুই পদ্ধতিতেই টেস্টিং গুরুত্বপূর্ণ, কারণ এটি আপনার কোডের মান এবং কর্মক্ষমতা নিশ্চিত করতে সাহায্য করে।
Read more